package com.smartfast4j.backend.common.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.*;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * Jedis单机客户端实现
 */
public class JedisClientSingle implements JedisClient{

	//jedis连接池
	private static JedisPool jedisPool;

	/**
	 * 获取实例
	 *
	 * @return
	 */
	public static JedisClientSingle getInstance() {
		return new JedisClientSingle();
	}

	static {
		//读取相关的配置
		ResourceBundle resourceBundle = ResourceBundle.getBundle("redis");
		int maxActive = Integer.parseInt(resourceBundle.getString("redis.pool.maxActive"));
		int maxIdle = Integer.parseInt(resourceBundle.getString("redis.pool.maxIdle"));
		int maxWait = Integer.parseInt(resourceBundle.getString("redis.pool.maxWait"));

		String ip = resourceBundle.getString("redis.ip");
		int port = Integer.parseInt(resourceBundle.getString("redis.port"));
		int timeout = Integer.parseInt(resourceBundle.getString("redis.timeout"));
		String auth = resourceBundle.getString("redis.auth");
		JedisPoolConfig config = new JedisPoolConfig();
		//设置最大连接数
		config.setMaxTotal(maxActive);
		//设置最大空闲数
		config.setMaxIdle(maxIdle);
		//设置等待可用连接的最大时间
		config.setMaxWaitMillis(maxWait);
		//初始化连接池
		//jedisPool = new JedisPool(config, ip, port,timeout);
		//初始化连接池
		jedisPool = new JedisPool(config, ip, port,timeout,auth);
	}

	@Override
	public String get(String key) {
		Jedis jedis = jedisPool.getResource();
		String string = jedis.get(key);
		jedis.close();
		return string;
	}

	@Override
	public byte[] get(byte[] key) {
		byte[] value = null;
		Jedis jedis = jedisPool.getResource();
		try{
			value = jedis.get(key);
		}finally{
			jedis.close();
		}
		return value;
	}

	@Override
	public String set(String key, String value) {
		Jedis jedis = jedisPool.getResource();
		String string = jedis.set(key, value);
		jedis.close();
		return string;
	}

	@Override
	public byte[] set(byte[] key, byte[] value) {
		Jedis jedis = jedisPool.getResource();
		try{
			jedis.set(key,value);
		}finally{
			jedis.close();
		}
		return value;
	}

	@Override
	public byte[] set(byte[] key, byte[] value, int expire) {
		Jedis jedis = jedisPool.getResource();
		try{
			jedis.set(key,value);
			if(expire != 0){
				jedis.expire(key, expire);
			}
		}finally{
			jedis.close();
		}
		return value;
	}

	@Override
	public String hget(String hkey, String key) {
		Jedis jedis = jedisPool.getResource();
		String string = jedis.hget(hkey, key);
		jedis.close();
		return string;
	}

	@Override
	public long hset(String hkey, String key, String value) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hset(hkey, key, value);
		jedis.close();
		return result;
	}

	@Override
	public long incr(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.incr(key);
		jedis.close();
		return result;
	}

	@Override
	public long expire(String key, int second) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.expire(key, second);
		jedis.close();
		return result;
	}

	@Override
	public long ttl(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.ttl(key);
		jedis.close();
		return result;
	}

	@Override
	public long del(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.del(key);
		jedis.close();
		return result;
	}

	@Override
	public long hdel(String hkey, String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hdel(hkey, key);
		jedis.close();
		return result;
	}

	@Override
	public void setObject(byte[] key, byte[] value) {
		Jedis jedis = jedisPool.getResource();
		jedis.set(key,value);
		jedis.close();
	}

	@Override
	public byte[] getObject(byte[] key) {
		Jedis jedis = jedisPool.getResource();
		byte[] bytes = jedis.get(key);
		jedis.close();
		return bytes;
	}

	@Override
	public long del(byte[] key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.del(key);
		jedis.close();
		return result;
	}

	@Override
	public <T> void setObject(String key, T obj) {
		setObject(key.getBytes(),objectToByte(obj));
	}

	@Override
	public <T> T getObject(String key, Class<T> clazz) {
		return byteToObject(getObject(key.getBytes()),clazz);
	}

	@Override
	public Set<byte[]> keys(String pattern) {
		Set<byte[]> keys = null;
		Jedis jedis = jedisPool.getResource();
		try{
			keys = jedis.keys(pattern.getBytes());
		}finally{
			jedis.close();
		}
		return keys;
	}

	/**
	 * 清空数据
	 */
	@Override
	public void flushDB() {
		Jedis jedis = jedisPool.getResource();
		try{
			jedis.flushDB();
		}finally{
			jedis.close();
		}
	}

	@Override
	public Long dbSize() {
		Long dbSize = 0L;
		Jedis jedis = jedisPool.getResource();
		try{
			dbSize = jedis.dbSize();
		}finally{
			jedis.close();
		}
		return dbSize;
	}

	/**
	 * 把byte还原为Object
	 * @param bytes
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	private <T> T byteToObject(byte[] bytes,Class<T> clazz){
		ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
		ObjectInputStream in;
		T t = null;
		try {
			in = new ObjectInputStream(bi);
			t = (T) in.readObject();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return t;
	}

	/**
	 * 把对象转化为byte
	 * @param object
	 * @return
	 */
	private byte[] objectToByte(Object object){
		ByteArrayOutputStream bo = new ByteArrayOutputStream();
		byte[] bytes = null;
		try {
			ObjectOutputStream oo = new ObjectOutputStream(bo);
			oo.writeObject(object);
			bytes = bo.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return bytes;
	}

	public static JedisPool getJedisPool() {
		return jedisPool;
	}
}
